#include "includes.h"
#include "stm32f4xx.h"
#include "tools.h"

#define SYMBOL_GLOBALS
#include "sys_timer.h"
#undef SYMBOL_GLOBALS

static volatile uint32_t lo_unElapsedSecs, lo_unElapsedMSecs, lo_unCurSysticks;

static uint8_t lo_ubSysticksOfOneUS = 0;						//* 1微秒多少个时钟节拍
static uint8_t lo_ubMillisecondsOfOneSystick = 0;		//* 一个时钟节拍多少毫秒
 
//* systick中断服务函数,使用ucos时用到
void SysTick_Handler(void)
{	
	lo_unCurSysticks++;
	lo_unElapsedMSecs += lo_ubMillisecondsOfOneSystick;
	
	if(!(lo_unCurSysticks % OS_TICKS_PER_SEC))
		lo_unElapsedSecs++;
	
	//* OS开始跑了,才执行正常的调度处理  
	if(OSRunning == OS_TRUE)
	{
		OSIntEnter();	//* 进入中断
		OSTimeTick();	//* 调用ucos的时钟服务程序               
		OSIntExit();	//* 触发任务切换软中断
	}
}
			   
void OSSystimerInit(void)
{		
  RCC_ClocksTypeDef stClocks;
  
	lo_ubSysticksOfOneUS = SystemCoreClock / 1000000; 
	lo_ubMillisecondsOfOneSystick = 1000 / OS_TICKS_PER_SEC;	//* 代表OS可以延时的最小单位	   	
	lo_unElapsedSecs  = 0; 
	lo_unElapsedMSecs = 0; 
	lo_unCurSysticks  = 0;  
  
  RCC_GetClocksFreq(&stClocks);
  SysTick_Config(stClocks.SYSCLK_Frequency / OS_TICKS_PER_SEC - 1);
  NVIC_SetPriority (SysTick_IRQn, 1);  
}								    

void delay_us(uint32_t unDelayUS)
{		
	uint32_t unTicks;
	uint32_t unOldTime, unNowTime, unTimeCnt = 0;
	uint32_t unReload = SysTick->LOAD; //* 当前计数值
	
	unTicks   = unDelayUS * lo_ubSysticksOfOneUS; //* 需要的节拍数
	unTimeCnt = 0;
	OSSchedLock();
	{
		unOldTime = SysTick->VAL; //* 此时的计数值
		while(TRUE)
		{
			unNowTime = SysTick->VAL;
			if(unNowTime != unOldTime)
			{
				if(unNowTime < unOldTime)
					unTimeCnt += unOldTime - unNowTime;
				else 
					unTimeCnt += unReload - unNowTime + unOldTime;	
				
				unOldTime = unNowTime;
				if(unTimeCnt >= unTicks)	//* 延时到达
					break;
			}
		}
	}
	OSSchedUnlock();							    
}

void delay_ms(uint16_t usDelayMS)
{	
	//* 如果OS已经在跑了,并且不是在中断里面(中断里面不能任务调度)	
	if(OSRunning && !OSIntNesting)
	{		 
		//* 延时的时间大于OS的最少时间周期
		if(usDelayMS >= lo_ubMillisecondsOfOneSystick)		
   			OSTimeDly(usDelayMS / lo_ubMillisecondsOfOneSystick);
		
		//* OS已经无法提供这么小的延时了，剩余的采用普通延时
		usDelayMS %= lo_ubMillisecondsOfOneSystick;
	}
  
	delay_us((uint32_t)(usDelayMS * 1000));
}

void DelaymsByCount(uint16_t usDelayMS)
{
	uint16_t i;
	uint16_t j;
	for(j = 0; j < usDelayMS; j++)	
		for(i = 0; i < 8100; i++);	
}

void DelayusByCount(uint16_t usDelayUS)
{
	uint16_t	i;
	uint16_t j;
	for(j = 0; j < usDelayUS; j++)	
		for(i = 0; i < 81; i++);	
}

uint32_t GetElapsedSecs(void)
{
	return lo_unElapsedSecs;
}

uint32_t GetElapsedMSecs(void)
{
	return lo_unElapsedMSecs;
}

uint32_t GetCurSysticks(void)
{
	return lo_unCurSysticks;
}
